上一篇提到DOM 是一種樹狀結構,而樹狀結構特別擅長查找資料。
因此這篇章就是要來認識「查找 DOM 元素」的相關語法。
查找 DOM 元素有兩種途徑:
首先我們先從選出特定 DOM 節點開始:
這次的案例:
語法:
document.querySelector(CSS-selector)
querySelector
用 CSS 選擇器來找元素,因此在括號裡下字串的方式,和平常寫 CSS 選擇器的邏輯是一模一樣。我們就來試試看來把裡的選項抓出來:
但如果我今天想要抓出所有的話就不能使用這個,我們可以試一下:
我們可以看到使用這個methods只會return 第一個滿足條件的element。
因此如果我們想要抓出全部的就必須使用另外一個methods。
語法:
document.querySelectorAll(CSS-selector)
這樣所有滿足條件的都會 return 。
另外我們注意看一下,return 回來的是一個NodeList,什麼是NodeList啊?
NodeList
是一個 JavaScript Object,它表示了一個節點(Node)的集合。
NodeList
很類似於Array ,但它並不是真正的 Array。
它不能新增刪除元素,只有幾個簡單的唯讀操作:
length
forEach
這個系列的語法是用字串來搜尋,不是 CSS 選擇器。
我們在昨天有提到『大多數人使用 querySelector 系列而不使用 get 系列』,但有一個語法是例外,那就是getElementById
。
至於原因我詢問了chat GPT,我是覺得蠻合理的啦,大家也可以看一下:
getElementById
是一個簡單的方法,適合於簡單的頁面操作。只需要提供元素的 ID,就可以快速地獲取該元素,不需要特別的選擇器語法。getElementById
是一個非常快速的方法,因為它在 DOM 中直接使用元素的 ID 進行查找,而不需要額外的選擇器解析和比對。getElementById
取得的元素確實是唯一的,不會有多個元素匹配。然而,也有一些限制和考慮因素:
getElementById
只能使用元素的 ID 進行選取。如果您想使用其他屬性或複雜的選擇器來選取元素,則需要使用其他 DOM 選取方法,如 querySelector
或 querySelectorAll
。getElementById
可能無法正確地找到這些動態添加的元素。現在我們先來學習如何新增element,並呈現在畫面上。
我們會利用到3個語法:
document.createElement
新增一個元素NODE.innerHTML
修改元素的文字NODE.appendChild
將元素插入現有 DOM 結構中:我們可以看到上面這個圖片,html的body裡面,只有一個的標籤但是,因為我們在JavaScript上打上了3段code,就讓我們的畫面多出了一段文字。這就是最基本的DOM的語法。
innerText
和 textContent
通常都被使用於「取得元素內的文字」,但兩者之間有什麼差別?
在MDN上是這麼說的:
Node.innerText
是一個代表節點及其後代之「已渲染」(rendered)文字內容的屬性。
**Node.textContent**
屬性表示了節點或其後代的文字內容。
總結來說,如果您需要操作元素的 HTML 內容,可以使用 innerHTML
。如果您只需要處理元素的純文本內容,則應使用 innerText
。
我們在剛剛的案例有一個語法NODE.appendChild
將元素插入現有 DOM 結構中,除了這個以外我們還有其他兩個方法:
NODE.insertBefore
NODE.replaceChild
我們來認識一下這三個方法的不同吧
NODE.appendChild
將一個節點附加到另一個節點的子節點列表的末尾。
圖片來源:AC教案
NODE.insertBefore
在指定節點之前插入新的節點。
圖片來源:AC教案
NODE.replaceChild
替換一個子節點為另一個節點。
圖片來源:AC教案
在了解後,我們來用這3個方法把剛剛案例完成吧。
感覺有點冗長,但主要是為了復原原本的例子,早知道原本範例打少一點XDD
這是一個IE不支援的語法,但….IE已經不在了~~~所以全部的瀏覽器都可以用XDD
圖片來源:AC教案
const container = document.querySelector(".card-body");
const h1 = document.createElement("h1");
h1.innerHTML = "Professional Sports";
const ul = document.createElement("ul");
container.appendChild(h1);
container.appendChild(ul);
const li_1 = document.createElement("li");
const li_2 = document.createElement("li");
li_1.innerHTML = "NFL";
li_2.innerHTML = "MLB";
ul.prepend(li_1);
ul.append(li_2);
ul.prepend("NBA");
我們會看到:
這套語法的撰寫風格比較簡潔,而且同時可以插入節點或文字。提供給大家參考。
parentElement.removeChild(NODE)
這個方法是用來從指定的父節點中移除子節點 NODE
。例如:
const parent = document.querySelector(".parent");
const child = document.querySelector(".child");
parent.removeChild(child);
NODE.remove()
這個方法可以直接從 DOM 中移除特定的節點 NODE
。例如:
const element = document.querySelector(".element");
element.remove();
NODE.classList
這是一個用來操作節點的 class 名稱的屬性。它會回傳一個類似陣列的物件,可以用來新增、刪除、查看 class 名稱。
const element = document.querySelector(".element");
element.classList.add("new-class");//增加
element.classList.remove("old-class");//刪除
NODE.className = className
這個屬性直接設定節點的 class 名稱,但注意這會將目前節點的所有 class 都替換掉。
const element = document.querySelector(".element");
element.className = "new-class";
DOM 也有提供 style
屬性,例如:NODE.style.backgroundColor
,但為了讓程式碼一目瞭然地被歸類在它們應該在的位置,建議還是先寫好 CSS 文件,再透過 classList
等方法去修改樣式。
DOM真的是我目前為止打最久的一個主題吧(未來的原型可能會超過),主要原因有兩個:1.真的很久沒有用這些語法了都忘了差不多了。2.就是我之前的筆記看不懂…導致我再回去把課程重上。
這次的教訓就是,筆記要認真做而且三不五時要回去更新,之前做筆記還會分發芽期、培育期、長青期,目的就是要讓自己回去檢視過去是否有理解錯誤的地方,結果這次在整理筆記發先我所有的筆記都是發芽期,培育期少之又少,長青期更是完全沒有。
明天就是遍歷(traverse)了,終於要結束這個主題了~